<?php
namespace Easy;

use Easy\Exception\NotFoundError;

class LoadClass
{
    const LOAD_NAMESPACE = 1;
    const LOAD_PATHHASH  = 2;

    private $scriptPHP = [];

    private $clsArr = [];

    private $clsUriRule = [];

    public function __construct($scriptPHP = [])
    {
        $this->scriptPHP = $scriptPHP;
    }

    public static function loadByNamespace($class)
    {
        $fileExt = EXT;
        if (strpos($class, "Easy\\") !== false) {
            $fileDir = EASY_LIB_PATH;
        } else {
            if (false !== strpos($class, '\\')) {
                $fileDir = APP_PATH;
            } else {
                $fileDir = LIB_PATH . '/';
                $fileExt = '.php';
            }
        }
        $filename = $fileDir . str_replace('\\', '/', $class) . $fileExt;

        if (is_file($filename)) {
            include (string)$filename;
        }
    }

    public static function loadCoreFile()
    {
        self::initSysConst();
        Storage::connect(STORAGE_TYPE);
        $runtimefile = RUNTIME_PATH . '~runtime.php';
        if (Storage::has($runtimefile)) {
            Storage::unlink($runtimefile);
        }
        $content = '';
        $mode    = include EASY_PATH . 'Conf/autoload.php';
        foreach ($mode['core'] as $file) {
            if (file_exists($file)) {
                include $file;
                if (!APP_DEBUG) {
                    $content .= compile($file);
                }
            }
        }
        foreach ($mode['config'] as $key => $file) {
            if (file_exists($file)) {
                is_numeric($key) ? C(load_config($file)) : C($key, load_config($file));
            }
        }
        // 设置系统时区
        date_default_timezone_set(C('DEFAULT_TIMEZONE'));
    }

    private static function initSysConst()
    {
        // 定义当前请求的系统常量
        define('NOW_TIME', $_SERVER['REQUEST_TIME']);
        define('REQUEST_METHOD', isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET');
        define('IS_GET', REQUEST_METHOD == 'GET' ? true : false);
        define('IS_POST', REQUEST_METHOD == 'POST' ? true : false);
        define('IS_PUT', REQUEST_METHOD == 'PUT' ? true : false);
        define('IS_DELETE', REQUEST_METHOD == 'DELETE' ? true : false);
        define('IS_AJAX',
            ((isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')) ? true : false);
    }


    public static function loadByPathHash($class)
    {
        if (strpos($class, "Easy\\") !== false) {
            $fileExt  = EXT;
            $fileDir  = EASY_LIB_PATH;
            $filename = $fileDir . str_replace('\\', '/', $class) . $fileExt;
        } else {
            $clsArr   = Router::getClsHash();
            $filename = @$clsArr[$class];
        }
        if (is_file($filename)) {
            include (string)$filename;
        }
    }

    public static function initClsHash($scriptsPHP)
    {
        if (!$scriptsPHP) {
            return;
        }
        $loadCLS  = new LoadClass($scriptsPHP);
        $allClass = $loadCLS->getAllClass();
        $uriCls   = $loadCLS->getRuiRule();
        Router::setClsHash($allClass);
        Router::setClsUriHash($uriCls);
    }

    public function getAllClass()
    {
        if (is_array($this->scriptPHP)) {
            foreach ($this->scriptPHP as $path) {
                $this->scanDir($path);
            }
        } else {
            $this->scanDir($this->scriptPHP);
        }

        return $this->clsArr;
    }

    public function getRuiRule()
    {
        return $this->clsUriRule;
    }

    private function scanDir($dirPath)
    {
        $current_dir = opendir($dirPath);
        while (($file = readdir($current_dir)) !== false) {
            $sub_dir = $dirPath . DIRECTORY_SEPARATOR . $file;
            if ($file == '.' || $file == '..') {
                continue;
            } else {
                if (is_dir($sub_dir)) {
                    $this->scanDir($sub_dir);
                } else {
                    $fileExtension = substr(strrchr($sub_dir, '.'), 1);
                    if ('php' == strtolower($fileExtension)) {
                        $this->appendClass($this->getFileCLS($sub_dir));
                    }
                }
            }
        }
    }

    private function appendClass($clsArr)
    {
        $this->clsArr = array_merge_recursive($this->clsArr, $clsArr);
    }

    private function appendUriRUle($clsName, $uriRule)
    {
        $this->clsUriRule[$uriRule] = $clsName;
    }

    private function getFileCLS($fileName)
    {
        $clsArr    = [];
        $handle    = @fopen($fileName, "r");
        $namespace = '';
        $i         = 1;
        while (!feof($handle)) {
            $buffer = fgets($handle, 102400);
            preg_match_all('/\/\/@URI_RULE:\s{1,}((\/[a-zA-Z0-9_]{1,}){1,})\/\$method/', $buffer, $uriMatch);//获取路由规则
            $buffer = addslashes($buffer);
            preg_match_all("/^\s*(class|interface|abstract\s{1,}class|namespace)\s{1,}(([a-zA-Z_0-9]*)(\\\\[a-zA-Z_0-9]*)*){?/i",
                $buffer,
                $match);

            $clsType = isset($match[1][0]) ? strtolower($match[1][0]) : null;
            if (!$clsType) {
                continue;
            }
            if ($clsType == 'namespace') {
                $namespace = stripslashes($match[2][0]) . "\\";
            } else {
                if (isset($match[2][0]) && $match[2][0]) {
                    $clsName          = stripslashes($match[2][0]);
                    $clsName          = $namespace . $clsName;
                    $clsArr[$clsName] = $fileName;
                    if (isset($uriMatch[0][0]) && $uriMatch[0][0]) {
                        $this->appendUriRUle($clsName, $uriMatch[1][0]);
                    }
                }
            }
            $i++;
        }
        fclose($handle);

        return $clsArr;
    }
}
